﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.IO.IsolatedStorage;

namespace Browser
{
    public partial class Polka : System.Web.UI.Page
    {

        List<string> listBox2Items;
        List<string> listBox3Items;
        List<string> listBox4Items;
        List<string> listBox5Items;
         List<string> listBox6Items;
         List<string> listBox7Items;

        private string selectedClass = "";

        private string userName = "";

        protected void Page_Load(object sender, EventArgs e)
        {
            if (Session["loggedin"] == null || (bool)Session["loggedin"] != true)
                Response.Redirect("login.aspx?login=login");

            if (Session["fileUpdated"] == null || (bool)Session["fileUpdated"] != true)
                Response.Redirect("upload.aspx");

            userName = (string)Session["username"];

            //si chargement de la page pour la première fois 
            // la page_load n'est pas appelé aprés le déclenchement d'un evenement 
            if (!Page.IsPostBack)
            {

                string absPath = GetUserDirectory() + "manifeste.xml";
                XDocument doc = XDocument.Load(absPath);

                ListClass.Items.Clear();
                XElement root = doc.Root;
                XElement polkas = root.Descendants("polkas").FirstOrDefault();
                IEnumerable<XElement> listClassPolka = polkas.Descendants("polka");
                ListClass.Items.Add("créer");
                ListClass.Items.AddRange(listClassPolka.Select(elt => new ListItem(elt.Attribute("nom").Value)).ToArray());

            }
        }

        public string GetUserDirectory()
        {
            return Server.MapPath(".") + @"\xml\" + userName + @"\dico\";
        }

        #region GetChilds

        // renvoi le noeud correspond à la classe polka dans le nom est passé en paramètre
        // les information qui se trouve dans manifeste 

        private XElement getFicPolka(String item)
        {
            XDocument doc = XDocument.Load(GetUserDirectory() + item + ".xml");
            XElement root = doc.Root;
            //XElement mynode = root.Descendants("polka").FirstOrDefault();

            if (root == null) return null;
            return root;
        }
        private XElement getClassByName(String item)
        {
            XDocument doc = XDocument.Load(GetUserDirectory() + "manifeste.xml");
            XElement root = doc.Root;
            XElement polkas = root.Descendants("polkas").FirstOrDefault();

            if (polkas == null)
                return null;

            XElement myNode = polkas.Descendants("polka")
                .Where(elt => elt.Attribute("nom").Value.ToLower() == item.ToLower())
                .FirstOrDefault();

            if (myNode == null)
                return null;
            else return myNode;
        }
        private XElement getClassById(int id)
        {
            XDocument doc = XDocument.Load(GetUserDirectory() + "manifeste.xml");
            XElement root = doc.Root;
            XElement polkas = root.Descendants("polkas").FirstOrDefault();

            if (polkas == null)
                return null;
            XElement myNode = polkas.Descendants("polka")
                .Where(elt => (int.Parse(elt.Attribute("id").Value)) == id).FirstOrDefault();
            if (myNode == null)
                return null;
            else return myNode;
        }

        private List<string> getList(string name, string noeud)
        {
            string n = noeud + "s";
            XElement noeudPolka = getFicPolka(name); // je récupere le root du fichier de la classe sélectionner 
            XElement noeudFils = noeudPolka.Element(n); // je récupère le noeud fils de polka : methodClasses, methodInstances, attrClasses, attrInstances
            if (noeudPolka == null) return null;
            List<string> listChilds = noeudFils.Descendants(noeud)  //methodClasse, methodInstance, attrClasse, attrInstance
                .Select(elt => elt.Attribute("nom").Value).ToList();   

            return listChilds;
        }
        private IEnumerable<XElement> getNoeud(string name, string noeud)
        {
            return (IEnumerable <XElement>)getList(name, noeud);
        }
   
       /* private IEnumerable<XElement> getINoeudLocalVariable(String item, string method)
        {
            XElement mynode = getFicPolka(item);
            //List<string> methodInst = getMethodInst(item);// renvoie tt les methodes d'instance de la class item
            IEnumerable<XElement> methodsInst = getMethodClassNoeud(item);
            XElement myMethod = methodsInst.Where(elt => elt.Attribute("nom").Value.ToLower() == method.ToLower()).FirstOrDefault();

            XElement variableLocales = myMethod.Element("variableLocales");
            if (variableLocales == null) return null;

            IEnumerable<XElement> variableLocaleElements = variableLocales.Descendants("variableLocale");


            return variableLocaleElements;

        }
        private IEnumerable<XElement> getCNoeudLocalVariable(String item, string method)
        {
            XElement mynode = getFicPolka(item);

            IEnumerable<XElement> methodsClass = getMethodClassNoeud(item);
            XElement myMethod = methodsClass.Where(elt => elt.Attribute("nom").Value.ToLower() == method.ToLower()).FirstOrDefault();


            XElement variableLocales = myMethod.Element("variableLocales");
            if (variableLocales == null) return null;

            IEnumerable<XElement> variableLocaleElements = variableLocales.Descendants("variableLocale");

            return variableLocaleElements;

        }
        private IEnumerable<XElement> getCNoeudParametre(string item, string method)
        {
            XElement mynode = getFicPolka(item);

            IEnumerable<XElement> methodsClass = getMethodClassNoeud(item);
            XElement myMethod = methodsClass.Where(elt => elt.Attribute("nom").Value.ToLower() == method.ToLower()).FirstOrDefault();


            XElement parametres = myMethod.Element("parametres");
            if (parametres == null) return null;
            IEnumerable<XElement> parametreElements = parametres.Descendants("parametre");

            return parametreElements;

        }
        private IEnumerable<XElement> getINoeudParametre(string item, string method)
        {
            XElement mynode = getFicPolka(item);

            IEnumerable<XElement> methodsClass = getMethodClassNoeud(item);
            XElement myMethod = methodsClass.Where(elt => elt.Attribute("nom").Value.ToLower() == method.ToLower()).FirstOrDefault();


            XElement parametres = myMethod.Element("parametres");
            if (parametres == null) return null;

            IEnumerable<XElement> parametreElements = parametres.Descendants("parametre");
            return parametreElements;
        }


        private List<string> getClistVariable(string item, string method)
        {
            return getCNoeudLocalVariable(item, method).Select(elt => elt.Attribute("nom").Value).ToList();
        }
        private List<string> getIListVariable(string item, string method)
        {
            return getINoeudLocalVariable(item, method).Select(elt => elt.Attribute("nom").Value).ToList();
        }
        private List<string> getClistParameter(string item, string method)
        {
            return getCNoeudParametre(item, method).Select(elt => elt.Attribute("nom").Value).ToList();
        }
        private List<string> getIListParametre(string item, string method)
        {
            return getINoeudParametre(item, method).Select(elt => elt.Attribute("nom").Value).ToList();
        }*/


      
        private void initClass(string nameClass,int idAncetre)
        {

            XDocument doc = XDocument.Load(GetUserDirectory() + "manifeste.xml");
            XDocument doc2 = new XDocument(); //.Load(GetUserDirectory() + nameClass + ".xml");

            //var item = nameClass;// ListClass.SelectedItem.Text;

            XElement descInManifeste = getClassByName(nameClass);
            XElement noeudClass = getFicPolka(nameClass);
            int idClasse = int.Parse(descInManifeste.Attribute("id").Value);

            XElement descr = new XElement("descr");
            XElement desc = new XElement("descendants");
            XElement attrInst = new XElement("attrInstances");
            attrInst.Add(new XElement("attrInstance",
                                           new XAttribute("id", "1"),
                                           new XAttribute("nom", "maClasse"),
                                           new XAttribute("value", idClasse),
                                           new XAttribute("type", "")));
            
            XElement attrClass = new XElement("attrClasses");
             attrClass.Add( new XElement ( "attrClasse", 
                                           new XAttribute("id","1"), 
                                           new XAttribute ("nom" ,"super"),
                                           new XAttribute("value",idAncetre),
                                           new XAttribute( "type","")));

            XElement methodI = new XElement("methodInstances");
            XElement methodC = new XElement("methodClasses");

            descInManifeste.Add(descr, desc);
            //doc.Root.Add(descInManifeste);
            

            noeudClass.Add(attrInst, attrClass, methodI, methodC);
            doc2.Add(noeudClass);

            doc2.Save(GetUserDirectory() + nameClass + ".xml");
            doc.Save(GetUserDirectory() +"manifeste.xml");
            //return noeudClass;
        }
        private int getMaxId()
        {
            XDocument doc = XDocument.Load(GetUserDirectory() + "manifeste.xml");
            XElement root = doc.Root;

            XElement polkas = root.Descendants("polkas").FirstOrDefault();
            IEnumerable<XElement> listClass = polkas.Descendants("polka");

            int a = listClass.Count();
            int maxId = listClass.Select(v => int.Parse(v.Attribute("id").Value)).Max();

            return maxId;

        }
       
        private void mettreAjour()
        {

            string ancetre = ListClass.SelectedValue;
            string nameNewClass = FirstLetterUpper(Editor.Text);

            //je parcours le manifeste et je récupère le id de la classe sélectionner 
            int idAncetre = int.Parse(getClassByName(ancetre).Attribute("id").Value);

            XElement superClassInManifeste = getClassById(idAncetre);
            XElement superClassFic = getFicPolka(ancetre);

            XElement desc = superClassInManifeste.Descendants("descendants").FirstOrDefault();
            //desc.Add(new XElement("descendant", new XAttribute("id", newId)));
            int newId = getMaxId() + 1;


            XDocument doc1 = XDocument.Load(GetUserDirectory() + "manifeste.xml");

            string newDoc = GetUserDirectory() + nameNewClass + ".xml";
            //XDocument doc= new XDocument(Server.MapPath(newDoc));
            XDocument doc2 = new XDocument();
            //XDocument doc2 = XDocument.Load(Server.MapPath("Dico\\"+nameNewClass + ".xml"));

            doc1.Root.Element("polkas").Descendants("polka")
            .Where(elt => (int.Parse(elt.Attribute("id").Value)) == idAncetre)
            .Descendants("descendants").FirstOrDefault().Add(new XElement("descendant", new XAttribute("id", newId)));

            doc1.Root.Element("polkas").Add(new XElement("polka",
                                                new XAttribute("id", newId),
                                                new XAttribute("nom", Editor.Text),
                                                new XAttribute("existDebut", true)));

            doc1.Save(GetUserDirectory() + "manifeste.xml");

            doc2.Add(new XElement("polka", new XAttribute("id", newId), new XAttribute("ancetre", idAncetre)));

            doc2.Save(newDoc);

            initClass(nameNewClass,idAncetre);

        }

        #endregion


        // Retourne le string entré en paramètre avec
        // une majuscule comme première lettre
        private string FirstLetterUpper(string str)
        {
            char[] letters = str.ToCharArray();
            letters[0] = char.ToUpper(letters[0]);

            return new string(letters);
        }


        #region Evenement
        protected void ListClass_SelectedIndexChanged(object sender, EventArgs e)
        {
            String item = ListClass.SelectedItem.Text;

            ListAttrInstances.Items.Clear();
            ListAttrClass.Items.Clear();
            ListMethodClass.Items.Clear();
            ListMethodInstance.Items.Clear();


            if (item == "créer")
            {
                //si on désire cérer une nouvelle classe

                EtatEdition.Text = "création d'une classe";
                ActionDispo.Items.Add("saisie le nom de la classe");
                this.Editor.Focus();
                //Label.Text = "à valider";
                ActionDispo.Items.Add(new ListItem("désirez vous un ancetre"));

            }
            else
            {
                if (Label.Text == "sélectionner un ancetre")
                {
                    mettreAjour();
                }
                else
                {

                    EtatEdition.Text = " la classe" + "" + item;

                    listBox2Items =  getList(item, "attrInstance");
                    listBox3Items =  getList(item, "attrClasse");
                    listBox4Items =  getList(item, "methodInstance");
                    listBox5Items =  getList(item, "methodClasse");

                    if (listBox2Items == null)
                        return;
                    if (listBox3Items == null)
                        return;

                    if (listBox4Items == null)
                        return;

                    if (listBox5Items == null)
                        return;

                    ListAttrInstances.Items.AddRange(listBox2Items.Select(s => new ListItem(s)).ToArray());
                    ListAttrClass.Items.AddRange(listBox3Items.Select(s => new ListItem(s)).ToArray());
                    ListMethodInstance.Items.AddRange(listBox4Items.Select(s => new ListItem(s)).ToArray());
                    ListMethodClass.Items.AddRange(listBox5Items.Select(s => new ListItem(s)).ToArray());
                }
            }
        }

        protected void ListAttrInstances_SelectedIndexChanged(object sender, EventArgs e)
        {
            //listSelected = "AttrInst";
            //NewItem.Text = " New Attr Inst";

            /*var item = ListAttrInstances.SelectedItem.Text;
            var listBox3Items = GetMethodInst(item);
            ListAttrInstances.Items.Clear();

            if (listBox3Items == null)
                return;

            ListAttrInstances.Items.AddRange(listBox3Items.Select(s => new ListItem(s)).ToArray());*/
        }

        protected void ListAttrClass_SelectedIndexChanged(object sender, EventArgs e)
        {

            //listSelected = "AttrClass";
            //NewItem.Text = " New Attr Class";

            /* var item = ListAttrClass.SelectedItem.Text;
             var listBox4Items = GetMethodClass(item);
             ListAttrClass.Items.Clear();

             if (listBox4Items == null)
                 return;

             ListAttrClass.Items.AddRange(listBox4Items.Select(s => new ListItem(s)).ToArray());*/
        }

      /*  protected void ListMethodInstance_SelectedIndexChanged(object sender, EventArgs e)
        {
            //listSelected = "MethodInst";
            //NewItem.Text = "New Method Inst";

            var method = ListMethodInstance.SelectedItem.Text;
            var listBox6Items = getList(selectedClass, method);
            var listBox7Items = getList(selectedClass, method);

            //ListLocalVariable.Items.Clear();
            //ListParametre.Items.Clear();

            if (listBox6Items == null)
                return;
            if (listBox7Items == null)
                return;

            ListLocalVariable.Items.AddRange(listBox6Items.Select(s => new ListItem(s)).ToArray());
            ListParametre.Items.AddRange(listBox7Items.Select(s => new ListItem(s)).ToArray());

        }

        protected void ListMethodClass_SelectedIndexChanged(object sender, EventArgs e)
        {
            //listSelected = "MethodClass";
            // NewItem.Text = " New Method Class";
            var method = ListMethodClass.SelectedItem.Text;
            var listBox6Items = getClistVariable(selectedClass, method);
            var listBox7Items = getClistParameter(selectedClass, method);

            ListLocalVariable.Items.Clear();
            ListParametre.Items.Clear();

            if (listBox6Items == null)
                return;
            if (listBox7Items == null)
                return;

            ListLocalVariable.Items.AddRange(listBox6Items.Select(s => new ListItem(s)).ToArray());
            ListParametre.Items.AddRange(listBox7Items.Select(s => new ListItem(s)).ToArray());
        }

        protected void ListLocalVariable_SelectedIndexChanged(object sender, EventArgs e)
        {
            listSelected = "LocalVariable";
            //NewItem.Text = " New Local Variable";
            var item = ListMethodInstance.SelectedItem.Text;
            var listBox6Items = getClistVariable(selectedClass, item);

            ListLocalVariable.Items.Clear();

            if (listBox6Items == null)
                return;

            ListLocalVariable.Items.AddRange(listBox6Items.Select(s => new ListItem(s)).ToArray());

        }

        protected void ListParametre_SelectedIndexChanged(object sender, EventArgs e)
        {
            listSelected = "Param";
            //NewItem.Text = " New Parameter";
            var item = ListParametre.SelectedItem.Text;
            var listBox6Items = getClistParameter(selectedClass, item);
            ListParametre.Items.Clear();

            if (listBox6Items == null)
                return;

            ListParametre.Items.AddRange(listBox6Items.Select(s => new ListItem(s)).ToArray());
        }*/

        #endregion

     


        protected void Valider_Click(object sender, EventArgs e)
        {
            selectedClass = ListClass.SelectedValue;
            ListClass.Items.Add(new ListItem(FirstLetterUpper(Editor.Text))); 
          
        }

        protected void ActionDispo_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ActionDispo.SelectedValue == "désirez vous un ancetre")
            {
               Label.Text = "sélectionner un ancetre";
            }

            if (ActionDispo.SelectedValue == "saisie le nom de la classe")
            {
               Label.Text = "entrez le nom";
            }
        }

        
       /* private List<string> getParaVarLocal(string name)
          // prend le nom de la méthode 
        {
            string classSelected = ListClass.SelectedValue;
            string methodSelected = ListMethodInstance.SelectedValue;
            
            
            XElement mymethod = getNoeud(classSelected, "methodInstance").Where(elm => elm.Attribute("nom").Value == methodSelected).FirstOrDefault();
            List<string> parametres = mymethod.Descendants("parametres").Select(elt => elt.Attribute("nom").Value).ToList();
            List<string> variableLocales = mymethod.Descendants("variableLocales").Select(elt => elt.Attribute("nom").Value).ToList();

           
        }*/

        protected void ListMethodInstance_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Une fois une méthodes est sélectionner on itialise la liste des parametres et des variables locales 

            string classSelected = ListClass.SelectedValue;
            string methodSelected = ListMethodInstance.SelectedValue;


            XElement mymethod = getNoeud(classSelected, "methodInstance").Where(elm => elm.Attribute("nom").Value == methodSelected).FirstOrDefault();
            List<string> parametres = mymethod.Descendants("parametres").Select(elt => elt.Attribute("nom").Value).ToList();
            List<string> variableLocales = mymethod.Descendants("variableLocales").Select(elt => elt.Attribute("nom").Value).ToList();
            
            listBox6Items = variableLocales;
            listBox7Items = parametres;

            ListParametre.Items.AddRange (listBox6Items.Select(s => new ListItem(s)).ToArray());
            ListLocalVariable.Items.AddRange (listBox7Items.Select(s => new ListItem(s)).ToArray());
            
                
        }

        protected void ListMethodClass_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        protected void ListLocalVariable_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        protected void ListParametre_SelectedIndexChanged(object sender, EventArgs e)
        {

        }





    }
}
